package com.conph.moring.core;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class MecProxy {
	/*实现AOP方式的代理机制
	 * 思路：
	 * 给出一个类的类型或者对象，通过beanFactory产生它的代理对象，和mecProxy对象
	 * 此时可以添加拦截器，以便在通过该对象执行相关方法时，成功将其拦截。
	 * 分析其中的过程，一开始在接收到产生代理的请求时，构建出他的mecProxy对象和它的类名对应起来
	 * ，并且保存，mecProxy中存在他的拦截器链，提供增加拦截器、删除拦截器的方法。
	 * beanFactory提供给外部使用。所有的产生代理、给对应类添加拦截器的操作都将提供给外部使用。*/
	
	private Object proxy;
	private Object object;
	private boolean injection;
	
	protected void setInjection(boolean injection) {
		this.injection = injection;
	}

	public MecProxy() {
		injection = false;
	}

	protected boolean isInjection() {
		return injection;
	}
	
	@SuppressWarnings("unchecked")
	protected <T> T getProxy() {
		return (T) proxy;
	}
	
	protected void setProxy(Object proxy) {
		this.proxy = proxy;
	}
	
	@SuppressWarnings("deprecation")
	protected <T> T getCGLProxy(Class<?> klass) throws InstantiationException, IllegalAccessException {
		return cglProxy(klass, klass.newInstance());
	}
	
	protected <T> T getCGLProxy(Object object) {
		return cglProxy(object.getClass(), object);
	}

	@SuppressWarnings({ "unchecked" })
	private <T> T cglProxy(Class<?> klass, Object object) {
		this.object = object;
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(klass);
		enhancer.setCallback(new MethodInterceptor() {
			
			@Override
			public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
				return doInvoke(klass, method, object, args);
			}
		});
		
		return (T) enhancer.create();
	}
	
	
	@SuppressWarnings("deprecation")
	protected <T> T getJDKProxy(Class<?> klass) throws InstantiationException, IllegalAccessException {
		return jdkProxy(klass, klass.newInstance());
	}
	
	protected <T> T getJDKProxy(Object object) {
		return jdkProxy(object.getClass(), object);
	}
	
	@SuppressWarnings({ "unchecked" })
	private <T> T jdkProxy(Class<?> klass, Object object) {
		this.object = object;
		ClassLoader classLoader = klass.getClassLoader();
		Class<?>[] interfaces = klass.getInterfaces();
		
		return (T) Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler() {
			
			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				return doInvoke(klass, method, object, args);
			}
		});
	}
	
	private Object doInvoke(Class<?> klass, Method method, Object object, Object[] args) throws Exception {
		// 前置拦截
		//现在要的对这个实际操作的板块进行更改，抛弃之前的拦截器连，使用新的拦截器链（基于责任链）
		//此处的原理是相同的，只不过是在IntercepterFactory中更改了map中的键值。
		Object result = null;
		IntercepterTargetDefination itd 
			= new IntercepterTargetDefination(klass, method);
		if(!IntercepterFactory.getBeforeNodes(itd).doBefore(klass, method, args)) {
			return result;
		}
		try {
			result = method.invoke(object, args);
			// 滞后拦截
			result = IntercepterFactory.getAfterNodes(itd).doAfter(klass, method, result);
		} catch (Exception e) {
			//  异常拦截
			IntercepterFactory.getExceptionNodes(itd).doException(klass, method, e);;
			throw e;
		}
		return result;
	}
	
	protected Object getObject() {
		return object;
	}

}
